讓我們延續上一篇的例子~
假設現在的學生不僅僅是一般大學生了,還包含研究生,現在要他們交作業,但不同類型的學生要交的作業不同,做的事情也不一樣,此時我就必須將程式碼做大幅度的修改,如果又再多一種學生類型….(欲哭無淚)。
那如果我一開始就將學生作為一個抽象類別,並且定義好一些規範,讓不同種類的學生們各自去繼承他的話呢…
先介紹一下有關物件導向的術語,等等看程式碼時會比較有感覺!
術語 | 描述 |
---|---|
抽象類別(abstracl class) | 定義了一組相關類別的行為 |
類別(class) | 根據物件所具有的責任定義物件的類型。責任可以分為行為和狀態。這些分別是由方法和資料實作的 |
具體類別(concrete class) | 實作抽象類別某一特定類型行為的類別。具體類別是一個概念特定、不變的實作 |
封裝(encapsulation) | 通常定義為資料隱藏,但最好將它看作任何形式的隱藏(類型、實作和設計等等) |
繼承(inheritance) | 一個類別繼承另一個類別,是指它接受了該類別的一些或者所有性質。起始類別稱為基礎類別、超類別、父類別或者一般類別,而繼承類別稱為衍生類別、子類別或者特殊化類別 |
實體(instance) | 類別的特例(總是一個物件)。類別的特殊實 體或者實體。每個物件都有自己的狀態。因此同一個類型(類別)可以有多個物件 |
實體化(instantiation) | 建立類別的一個實體的過程 |
介面(interface) | 介面與類別類似,但是只為其成員提供規約而不提供實作。它與只含有抽象成員的抽象類別很相似。程式設計的時候,如果需要幾個類別共用公共基礎類別中沒有的一些特性,而且希望確保每個類別自己實作這些特性(因為所有成員都是抽象的),就應該使用介面 |
多型(polymorphism) | 能夠用一種方式參照一個類別的不同衍生類別,但獲得的行為對應於所參照的衍生類別 |
公開(public) | 任何物件都能夠看見 |
保護(protected) | 只有這個類別及其衍生類別的物件能夠看見 |
私有(private) | 只有這個類別的物件能夠看見 |
前一篇提及,學生如何到下一堂課的地點 (使用介面)
public class Program
{
static void Main(string[] args)
{
// 我們給學生一個「去下一間教室」的規定,學生使用自己的方式到下一間教室
Student student = new Student();
student.goNextClassRoom();
}
}
public class Student : IStudentRule
{
// 介面有定義的屬性與方法名稱一定要實作
public string transportationType { get; set; }
public void goNextClassRoom()
{
transportationType = "腳踏車";
Console.WriteLine($"我使用{transportationType}到下一間教室");
}
}
public interface IStudentRule
{
// 介面定義好需要的屬性與方法名稱
string transportationType { get; set; }
void goNextClassRoom();
}
本篇介紹,如果學生不只是學生 (使用抽象類別)
public class Program
{
static void Main(string[] args)
{
// 一般生,給予共通屬性「學號」,實作一般生的寫作業方法,最後用共通的交作業方式
Student regularStudent = new RegularStudent{StudentId = 1};
var homework = regularStudent.WriteHomework();
regularStudent.SubmitHomeworkToTeacher(homework);
// 研究生,給予共通屬性「學號」,實作研究生的寫作業方法,最後用共通的交作業方式
Student graduateStudent = new GraduateStudent{StudentId = 2};
homework = graduateStudent.WriteHomework();
graduateStudent.SubmitHomeworkToTeacher(homework);
}
}
public abstract class Student
{
// 定義共有屬性
public int StudentId { get; set; }
// abstract屬性需要繼承者去實作
protected abstract string StudentType { get; set; }
// abstract方法不能先定義內容,需要繼承者去實作
public abstract string WriteHomework();
// virtaul方法可以先定義內容
public virtual void SubmitHomeworkToTeacher(string homework)
{
Console.WriteLine($"我是{StudentType},學號為{StudentId}號,作業內容是{homework},交作業給老師");
}
}
public class RegularStudent : Student
{
protected override string StudentType { get; set; } = "一般生";
public override string WriteHomework()
{
return $"專題報告";
}
}
public class GraduateStudent : Student
{
protected override string StudentType { get; set; } = "研究生";
public override string WriteHomework()
{
return $"碩士論文";
}
}
物件導向方法有效地限制了需求變更所帶來的影響!從上面的例子來看,我是老師,先定義好規範後,不用知道學生們是如何去寫作業,只要他們在自己的封裝內實作完成就好,也就是「物件自己負責自己」,最後在主程式裡(main),去呼叫定義好的方法名稱,就做完了,在主程式裡的責任也就相對少了許多。
好啦~ 我們明天再續,會講到UML統一建模語言